<?php

/**
 * 操作基类
 * @author ice.deng <ice.deng@qq.com>
 */
class BaseHandler
{
    /**
     * @var string 页面title
     */
    public $pageTitle;
    /**
     * @var string 页面keywords
     */
    public $pageKeywords;
    /**
     * @var string 页面description
     */
    public $pageDescription;
    /**
     * @var null|string 母模板
     */
    public $layout = null;

    private $_data = [];

    /**
     * @var Container
     */
    public $ci;
    /**
     * @var Application
     */
    public $app;

    /**
     * BaseHandler constructor.
     * @param Container $ci
     */
    public function __construct($ci)
    {
        $this->ci = $ci;
        $this->app = $ci->offsetGet('app');
        $this->pageTitle = $ci['site_name'];
        $this->pageKeywords = $ci['site_keywords'];
        $this->pageDescription = $ci['site_description'];
        $this->init();
    }

    /**
     * 返回该类的完整名称
     * @return string 此类的完整名称.
     */
    public static function className()
    {
        return get_called_class();
    }

    /**
     * 此方法在类构造函数执行后调用,用于实现子类初始化
     */
    public function init()
    {
    }

    /**
     * 模板处理
     * @param $template
     * @param array $data
     * @return mixed
     */
    public function render($template, array $data = [])
    {
        $view = $this->app->view;
        $data['handler'] = $this;
        $view->pageTitle = $this->pageTitle;
        $view->pageKeywords = $this->pageKeywords;
        $view->pageDescription = $this->pageDescription;
        $output = $view->render($template, $data);
        if ($this->layout != null) {
            $data['content'] = $output;
            $output = $view->render($this->layout, $data);
        }
        return $output;
    }

    /**
     * 获取对象的属性值
     *
     * php魔术方法,在未找到属性时会调用此方法
     * @param string $name 属性明
     * @return mixed 属性的值
     * @throws \Exception 如果属性未找到
     * @throws \Exception 如果属性为只写
     * @see __set()
     */
    public function __get($name)
    {
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {
            return $this->$getter();
        } elseif (method_exists($this, 'set' . $name)) {
            throw new \Exception('只写属性: ' . get_class($this) . '::' . $name);
        }
        return $this->arrayGet($this->_data, $name);
    }

    /**
     * 设置对象属性值
     *
     * php魔术方法,在未找到属性时会调用此方法
     * @param string $name 属性名称或事件名称
     * @param mixed $value 设置的属性值
     * @throws \Exception 属性未找到
     * @throws \Exception 属性为只读
     * @see __get()
     */
    public function __set($name, $value)
    {
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {
            $this->$setter($value);
        } elseif (method_exists($this, 'get' . $name)) {
            throw new \Exception('只读属性: ' . get_class($this) . '::' . $name);
        }
        $this->_data[$name] = $value;
    }

    /**
     * 检查此属性值是否存在
     *
     * php魔术方法, 调用`isset($object->property)`时会调用此方法
     *
     * @param string $name 属性名称或事件名称
     * @return boolean 属性值存在(不为空)
     * @see http://php.net/manual/en/function.isset.php
     */
    public function __isset($name)
    {
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {
            return $this->$getter() !== null;
        } else {
            return isset($this->_data[$name]);
        }
    }

    /**
     *
     * 设置对象属性值为空
     *
     * @param string $name 属性名称
     * @throws \Exception 只读属性
     * @see http://php.net/manual/en/function.unset.php
     */
    public function __unset($name)
    {
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {
            $this->$setter(null);
        } elseif (method_exists($this, 'get' . $name)) {
            throw new \Exception('只读属性: ' . get_class($this) . '::' . $name);
        }
        unset($this->_data[$name]);
    }

    /**
     * 获取是否存在此方法
     *
     * @param string $name 方法名
     * @return boolean
     */
    public function hasMethod($name)
    {
        return method_exists($this, $name);
    }

    /**
     * 获取数组中的制定键值
     * @param array $arr
     * @param $key
     * @param null $default
     * @return array|null
     */
    public function arrayGet(array $arr, $key, $default = null)
    {
        if (is_null($key)) {
            return $arr;
        }
        if (isset($arr[$key])) {
            return $arr[$key];
        }
        return $default;
    }
}